package net.yxsoft.service.infrastructure;

import com.jfinal.aop.Before;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.tx.Tx;
import net.yxsoft.bean.JsTreeNode;
import net.yxsoft.bean.JsTreeNodeFieldKey;
import net.yxsoft.enumclass.StateEnumCls;
import net.yxsoft.enumclass.VisibleEnumCls;
import net.yxsoft.kit.JsTreeNodeKit;
import net.yxsoft.enumclass.infrastructure.MenuTypeEnumCls;
import net.yxsoft.model.infrastructure.TsCode;
import net.yxsoft.model.infrastructure.TsMenu;
import net.yxsoft.model.infrastructure.TsPermission;
import net.yxsoft.service.common.BaseService;
import rapid.core.Authuser;
import rapid.core.ContextStateEnum;
import rapid.core.TResult;

import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Leo on 2016/5/13.
 */
public class MenuService extends BaseService {

  public static final MenuService INSTANCE = new MenuService();

  private final TsMenu tsmenuDao = new TsMenu().dao();


  /**
  * @MethodName: getMenuById
  * @Description: 根据菜单主键获取菜单信息
  * @param: menuId 菜单主键
  * @return * @return net.yxsoft.model.infrastructure.TsMenu
  * @throws
  * @date 2023/8/31 13:19
  * @author wj
  */
  public TsMenu getMenuById(String menuId) throws IllegalAccessException {
    TsMenu tsMenu = TsMenu.dao.findById(menuId);
    TsCode tsCode = new TsCode().dao().findFirst("select * from ts_code where CODETYPE = 'MENUTYPE' and LEAF = '2' and customid = ?",tsMenu.getMenuType());
    if(StrKit.notNull(tsCode) && StrKit.notNull(tsCode.getCodename())){
      //tsMenu.setMenuType(tsCode.getCodename());
      tsMenu.put("menu_type_ch",tsCode.getCodename());
    }
    tsMenu.put("TYPE_CH", MenuTypeEnumCls.getObject(MenuTypeEnumCls.class, tsMenu.getType()).getText());
    tsMenu.put("ENABLED_CH", StateEnumCls.getObject(StateEnumCls.class, tsMenu.getEnabled()).getText());
    tsMenu.put("VISIBLE_CH", VisibleEnumCls.getObject(VisibleEnumCls.class, tsMenu.getVisible()).getText());

    return tsMenu;
  }

  /**
  * @MethodName: saveMenu
  * @Description: 保存菜单信息
  * @param: menu 实体
   * @param: user
  * @return * @return rapid.core.TResult
  * @throws
  * @date 2023/8/31 13:19
  * @author wj
  */
  public TResult saveMenu(TsMenu menu, Authuser user) {
    boolean result = false;
    String operation = "";
    if(menu.getId() == null) {
      if(menu.getPid() == null) {
        menu.setPid(0); //第一级默认父ID为0
      }
      if(StrKit.notNull(menu.getCode())){
        //验证编号是否全局唯一
        List<TsMenu>  menus = new TsMenu().dao().find("select * from ts_menu where code = ?",menu.getCode());
        if(menus.size() > 0){
          return TResult.fail("该编号已存在！");
        }
      }
    if(menu.getPid() != 0){
      if(!"ORDINARYMENU".equals(menu.getMenuType())){
        if(menu.getMenuCode() == null || menu.getMenuCode() == ""){
          return TResult.fail("非普通菜单编号不能为空！");
        }
        List<TsMenu>  tsMenuList = new TsMenu().dao().find("select * from ts_menu where menu_type=? and menu_code = ?",menu.getMenuType(),menu.getMenuCode());
        if(tsMenuList.size() > 0){
          return TResult.fail("非普通菜单编号已存在！");
        }
      }
      if(menu.getMenuCode() != null || menu.getMenuCode() != ""){
        List<TsMenu>  tsMenuList = new TsMenu().dao().find("select * from ts_menu where menu_type=? and menu_code = ?",menu.getMenuType(),menu.getMenuCode());
        if(tsMenuList.size() > 0){
          return TResult.fail("非普通菜单编号已存在！");
        }
      }
    }
      result = menu.save();
      operation = "新增";
    } else {
      TsMenu tsMenu = TsMenu.dao.findById(menu.getId());
      tsMenu.set("NAME", menu.getName());
      tsMenu.set("CODE", menu.getCode());
      tsMenu.set("ICON", menu.getIcon());
      tsMenu.set("ENABLED", menu.getEnabled());
      tsMenu.set("VISIBLE", menu.getVisible());
      tsMenu.set("SORT_ID", menu.getSortId());
      tsMenu.set("PATH", menu.getPath());
      tsMenu.set("NOTE", menu.getNote());
      tsMenu.set("MENU_TYPE",menu.getMenuType());
      tsMenu.set("MENU_CODE",menu.getMenuCode());
      if(menu.getPid() != 0){
        if(!"ORDINARYMENU".equals(menu.getMenuType())){
          if(menu.getMenuCode() == null || menu.getMenuCode() == ""){
            return TResult.fail("非普通菜单编号不能为空！");
          }
          List<TsMenu>  tsMenuList = new TsMenu().dao().find("select * from ts_menu where menu_type=? and menu_code = ? and id <> ?",menu.getMenuType(),menu.getMenuCode(),menu.getId());
          if(tsMenuList.size() > 0){
            return TResult.fail("非普通菜单编号已存在！");
          }
        }
        if(menu.getMenuCode() != null || menu.getMenuCode() != ""){
          List<TsMenu>  tsMenuList = new TsMenu().dao().find("select * from ts_menu where menu_type=? and menu_code = ? and id <> ?",menu.getMenuType(),menu.getMenuCode(),menu.getId());
          if(tsMenuList.size() > 0){
            return TResult.fail("非普通菜单编号已存在！");
          }
        }
      }
      if(StrKit.notNull(menu.getCode())){
        //验证编号是否全局唯一
        List<TsMenu>  menus = new TsMenu().dao().find("select * from ts_menu where code = ? and id <> ?",menu.getCode(),menu.getId());
        if(menus.size() > 0){
          return TResult.fail("该编号已存在！");
        }
      }
      result = tsMenu.update();
      operation = "修改";
    }

    return success();
  }

  /**
  * @MethodName: deleteMenuById
  * @Description: 根据主键删除菜单
  * @param: menuId
   * @param: user
  * @return * @return boolean
  * @throws
  * @date 2023/8/31 13:20
  * @author wj
  */
  @Before(Tx.class)
  public boolean deleteMenuById(String menuId, Authuser user) throws SQLException {
    boolean result = false;
    if(StrKit.notBlank(menuId)) {
      try {
        deleteRelatedTerms(menuId, user);
        result = true;
      } catch(SQLException e) {
        throw e;
      }
    }

    return result;
  }

  /**
  * @MethodName: deleteMenus
  * @Description: 根据主键集合删除菜单
  * @param: menuIds  菜单主键集合
   * @param: user
  * @return * @return boolean
  * @throws
  * @date 2023/8/31 13:20
  * @author wj
  */
  @Before(Tx.class)
  public boolean deleteMenus(String[] menuIds, Authuser user) throws SQLException {
    boolean result = false;

    if(menuIds.length > 0) {
      try {
        for(String menuId : menuIds) {
          deleteRelatedTerms(menuId, user);
        }
        result = true;
      } catch(SQLException e) {
        throw e;
      }
    }

    return result;
  }

  /**
  * @MethodName: getMenusTree
  * @Description: 获取菜单树
  * @param:
  * @return * @return java.util.List<net.yxsoft.bean.JsTreeNode>
  * @throws
  * @date 2023/8/31 13:21
  * @author wj
  */
  public List<JsTreeNode> getMenusTree() throws NoSuchMethodException, SecurityException, InvocationTargetException, IllegalAccessException {
    JsTreeNodeFieldKey tnfk = new JsTreeNodeFieldKey("Id", "Name", "Pid");
    tnfk.setLeafKey("Pid");
    tnfk.setLeafValue("0");

    List<TsMenu> menulist = TsMenu.dao.find("SELECT ID, PID, NAME, CODE, TYPE FROM TS_MENU WHERE TYPE IS NOT NULL ORDER BY SORT_ID ASC");
    String type, code;
    for(TsMenu tsMenu : menulist) {
      //code = StrKit.isBlank(tsMenu.getCode()) ? "" : String.format("[%s]", tsMenu.getCode());
      code = "";
      if(tsMenu.getType().equals(MenuTypeEnumCls.MODULE.getValue())) {
        type = "M)";

      } else if(tsMenu.getType().equals(MenuTypeEnumCls.APP.getValue())) {
        type = "A)";

      } else if(tsMenu.getType().equals(MenuTypeEnumCls.FUNC.getValue())) {
        type = "F)";

      } else {
        type = "";
      }

      tsMenu.setName(type + tsMenu.getName() + code);
    }

    return JsTreeNodeKit.SerializeJsTreeData(tnfk, menulist);
  }

  /**
  * @MethodName: getMenuType
  * @Description: 根据菜单类型返回枚举类
  * @param: type 菜单类型
   * @param: r
  * @return * @return java.util.List<net.yxsoft.enumclass.infrastructure.MenuTypeEnumCls>
  * @throws
  * @date 2023/8/31 13:21
  * @author wj
  */
  public List<MenuTypeEnumCls> getMenuType(String type, boolean r) throws IllegalAccessException {
    List<MenuTypeEnumCls> menuType = new ArrayList<MenuTypeEnumCls>();
    menuType.add(MenuTypeEnumCls.getObject(MenuTypeEnumCls.class, type));
    if(r) {
      MenuTypeEnumCls _defaultType = new MenuTypeEnumCls("请选择...", "");
      menuType.add(0, _defaultType);
    }
    return menuType;
  }


  /**
  * @MethodName: getMenuTypeList
  * @Description: 根据父级菜单类型返回子级菜单类型可选集合
  * @param: type 菜单类型
  * @return * @return java.util.List<net.yxsoft.enumclass.infrastructure.MenuTypeEnumCls>
  * @throws
  * @date 2023/8/31 13:21
  * @author wj
  */
  public List<MenuTypeEnumCls> getMenuTypeList(String type) {
    List<MenuTypeEnumCls> menuType;
    if(StrKit.isBlank(type)) {
      menuType = MenuTypeEnumCls.UNDER_MODULE;
    } else {
      if(type.equals(MenuTypeEnumCls.MODULE.getValue())) {
        menuType = MenuTypeEnumCls.UNDER_MODULE;
      } else if(type.equals(MenuTypeEnumCls.APP.getValue())) {
        menuType = MenuTypeEnumCls.UNDER_PROGRAM;
      } else {
        menuType = MenuTypeEnumCls.empty();
      }
    }

    return menuType;
  }

  /**
  * @MethodName: getModelOperatingAuthorization
  * @Description:
  * @param: url
   * @param: userid
  * @return * @return java.util.List<com.jfinal.plugin.activerecord.Record>
  * @throws
  * @date 2023/8/31 13:21
  * @author wj
  */
  public List<Record> getModelOperatingAuthorization(String url, String userid) {

    List<Record> _r = Db.find("SELECT C.CODE FROM TS_UR_RELATION A\n" +
                                "INNER JOIN TS_PERMISSION B ON A.ROLE_ID=B.ROLE_ID \n" +
                                "INNER JOIN (SELECT * FROM TS_MENU WHERE PID IN (SELECT ID FROM TS_MENU WHERE PATH = ? AND TYPE='2')) C ON B.MENU_ID=C.ID\n" +
                                "WHERE A.USER_ID=? ", url, userid);

    return _r;
  }

  /**
  * @MethodName: deleteRelatedTerms
  * @Description: 删除菜单子项和关联项
  * @param: menuId 菜单ID
   * @param: user
  * @return * @return void
  * @throws
  * @date 2023/8/31 13:22
  * @author wj
  */
  private void deleteRelatedTerms(String menuId, Authuser user) throws SQLException {
    try {
      List<TsPermission> pers = TsPermission.dao.find("SELECT * FROM TS_PERMISSION WHERE MENU_ID = ?", menuId);
      if(pers.size() > 0) {
        for(TsPermission tsPermission : pers) {
          tsPermission.delete();
        }
      }

      TsMenu.dao.deleteById(menuId);

      List<TsMenu> menus = TsMenu.dao.find("SELECT ID FROM TS_MENU WHERE PID = ?", menuId);

      if(menus.size() > 0) {
        for(TsMenu tsMenu : menus) {
          deleteRelatedTerms(tsMenu.getId().toString(), user);
        }
      }
    } catch(SQLException e) {
      throw e;
    }
  }

  /**
  * @MethodName: getUserRoleMenuList
  * @Description:  获取登录用户使用的当前功能模块的按钮权限
  * @param: menuCode
   * @param: uid
  * @return * @return java.util.List<net.yxsoft.model.infrastructure.TsMenu>
  * @throws
  * @date 2023/8/31 13:22
  * @author wj
  */
  public List<TsMenu> getUserRoleMenuList(String menuCode, String uid) {
    if(StrKit.isBlank(menuCode)) {
      return null;
    }
    List<TsMenu> _returnData = new ArrayList<TsMenu>();
    String _strsql = String.format("\n" +
                                     "select e.* from ts_user a\n" +
                                     "inner join ts_ur_relation b on a.id = b.user_id\n" +
                                     "inner Join ts_role c on c.id = b.role_id\n" +
                                     "inner join ts_permission d on d.role_id = c.id\n" +
                                     "inner join ts_menu e on e.id = d.menu_id\n" +
                                     "where a.id='%s' and e.pid = (select id from ts_menu where code='%s' LIMIT 1)", uid, menuCode);
    _returnData = tsmenuDao.find(_strsql);
    return _returnData;
  }


  /**
  * @MethodName: getUserRoleMenuListByFunction
  * @Description: 后台方法权限验证
  * @param: functionCode
   * @param: uid
  * @return * @return rapid.core.TResult
  * @throws
  * @date 2023/8/31 13:22
  * @author wj
  */
  public TResult getUserRoleMenuListByFunction(String functionCode, String uid) {
    TResult _result = new TResult();
    if(StrKit.isBlank(functionCode)) {
      _result.setState(ContextStateEnum.FAIL);
      _result.setMessage("您没有当前操作权限。");
      return _result;
    }
    String _strsql = String.format("\n" +
                                     "select e.* from ts_user a\n" +
                                     "inner join ts_ur_relation b on a.id = b.user_id\n" +
                                     "inner Join ts_role c on c.id = b.role_id\n" +
                                     "inner join ts_permission d on d.role_id = c.id\n" +
                                     "inner join ts_menu e on e.id = d.menu_id\n" +
                                     "where a.id='%s' and e.code = '%s'", uid, functionCode);
    TsMenu _model = tsmenuDao.findFirst(_strsql);
    if(_model == null) {
      _result.setState(ContextStateEnum.FAIL);
      _result.setMessage("您没有当前操作权限。");
      return _result;
    } else {
      _result.setState(ContextStateEnum.SUCCESS);
      return _result;
    }
  }

}
